feat(oauth): allow upstream base URL overrides#4086
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces global and per-credential base URL overrides for the Claude and Codex API providers. It adds claude-base-url and codex-base-url configuration options, updates the respective executors to respect these overrides with fallback logic, and allows OAuth/file-backed credentials to specify a base_url or base-url to override the upstream endpoints. Additionally, corresponding unit tests have been added to verify the precedence and functionality of these overrides. There are no review comments, so we have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5430126af
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if baseURL == "" && cfg != nil { | ||
| baseURL = strings.TrimSpace(cfg.ClaudeBaseURL) |
There was a problem hiding this comment.
Keep provider override off API-key Claude auths
When claude-base-url is set, this fallback runs for every Claude auth that lacks Attributes["base_url"], including config claude-api-key entries where base-url is intentionally omitted. Those API-key credentials previously used https://api.anthropic.com; now they are sent to the provider-wide OAuth override, which contradicts the documented OAuth/file-backed scope and the commit note that API-key base-url behavior is unchanged. Gate this fallback on OAuth/file-backed credentials so API-key entries without a per-key base URL keep the official default.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 0f0f640. @chatgpt-codex-connector please review again.
| func codexCreds(a *cliproxyauth.Auth) (apiKey, baseURL string) { | ||
| return codexCredsWithConfig(nil, a) | ||
| } |
There was a problem hiding this comment.
Route Codex websocket/image paths through override
This legacy helper is still used by Codex paths that were not updated, so they cannot see codex-base-url: I checked CodexWebsocketsExecutor.Execute/ExecuteStream and the Codex OpenAI image handlers, which still call codexCreds(auth). With an OAuth Codex auth file that has no per-file base_url and a provider-wide codex-base-url, normal Codex execute/stream/compact requests use the override, but downstream WebSocket and image requests still fall back to https://chatgpt.com/backend-api/codex, bypassing the configured gateway.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 0f0f640. @chatgpt-codex-connector please review again.
a543012 to
98390fb
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 98390fb6d6
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| UpdatedAt: now, | ||
| } | ||
| if baseURL := authFileBaseURL(metadata); baseURL != "" { | ||
| a.Attributes["base_url"] = baseURL |
There was a problem hiding this comment.
Mirror auth-file base_url in FileTokenStore
This only adds the base_url/base-url mapping for watcher-synthesized auths, but the parallel file-token-store parser used by Manager.Load and SDK/utility callers still builds file auths in sdk/auth/filestore.go without Attributes["base_url"]. In contexts that load auth files through the token store rather than the watcher (for example embedded SDK use or fetch utilities), a Codex/Claude auth file with a per-account base_url is treated as if it had no per-auth override, so requests fall back to the provider-wide/default endpoint instead of the file's gateway.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 0f0f640. @chatgpt-codex-connector please review again.
98390fb to
38cb578
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 38cb578a86
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if baseURL := authFileBaseURL(metadata); baseURL != "" { | ||
| auth.Attributes["base_url"] = baseURL | ||
| } |
There was a problem hiding this comment.
Preserve per-auth base_url in remote stores
When the server is backed by Git/Postgres/ObjectStore token stores, auth JSON is loaded through GitTokenStore.readAuthFile, ObjectTokenStore.readAuthFile, or PostgresStore.List instead of this FileTokenStore path, and those loaders still don't copy base_url/base-url from metadata into Attributes["base_url"]. In that configuration a Claude/Codex OAuth record with a per-account base_url is treated as unset by claudeCredsWithConfig/codexCredsWithConfig, so it falls through to the provider-wide/default endpoint rather than the account-specific gateway.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 0f0f640. @chatgpt-codex-connector please review again.
38cb578 to
0f0f640
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f0f640a37
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| baseURL = strings.TrimSpace(a.Attributes["base_url"]) | ||
| } | ||
| if baseURL == "" && a.AuthKind() == cliproxyauth.AuthKindOAuth && cfg != nil { | ||
| baseURL = strings.TrimSpace(cfg.ClaudeBaseURL) |
There was a problem hiding this comment.
Trim Claude override URLs before request construction
When a newly-supported OAuth override is configured with a trailing slash, e.g. claude-base-url: http://proxy/ or an auth-file base_url, this returns that slash unchanged; the Claude request builders later concatenate fmt.Sprintf("%s/v1/messages?beta=true", baseURL) and .../count_tokens, producing //v1/.... Gateways with exact routing on /v1/messages will 404, while the Codex paths already use strings.TrimSuffix, so normalize the Claude override before returning it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0f0f640a37
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if auth.Attributes == nil { | ||
| auth.Attributes = make(map[string]string) | ||
| } | ||
| auth.Attributes["base_url"] = baseURL |
There was a problem hiding this comment.
Restrict base_url attributes to native OAuth providers
Because this helper copies base_url into Auth.Attributes for every provider, a simple file-backed plugin auth such as type: my-plugin with its own base_url is now treated as native OpenAI-compatible: sdk/cliproxy/service.go returns true from hasNativeOpenAICompatExecutorConfig whenever Attributes["base_url"] is set, so the plugin-executor branch in registerExecutorForAuth is skipped and an OpenAICompatExecutor is registered instead. Limit this copy to the native OAuth providers that actually consume it (e.g. Claude/Codex), or otherwise avoid setting the generic attr for plugin providers.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in ae57b1e. @chatgpt-codex-connector please review again.
0f0f640 to
641db43
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 641db4371b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| baseURL = strings.TrimSpace(cfg.ClaudeBaseURL) | ||
| } | ||
| if baseURL != "" { | ||
| baseURL = strings.TrimRight(baseURL, "/") |
There was a problem hiding this comment.
Normalize Claude base URLs consistently for config matching
When a claude-api-key entry uses a trailing slash in base-url and also relies on per-key settings such as cloak or experimental-cch-signing, this trims the auth-side URL to https://proxy while resolveClaudeKeyConfig still compares against strings.TrimSpace(entry.BaseURL) (https://proxy/). That mismatch makes the executor fail to find the matching config entry, so those per-key Claude settings are silently ignored even though the request URL itself works. Normalize the config-side base URL the same way before matching, or avoid using the trimmed value for config lookup.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in ae57b1e. @chatgpt-codex-connector please review again.
8bccbfa to
ae57b1e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae57b1e57a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| baseURL = strings.TrimSpace(a.Attributes["base_url"]) | ||
| } | ||
| if baseURL == "" && a.AuthKind() == cliproxyauth.AuthKindOAuth && cfg != nil { | ||
| baseURL = strings.TrimSpace(cfg.ClaudeBaseURL) |
There was a problem hiding this comment.
Honor metadata base URLs before the global fallback
When an OAuth Auth reaches this helper with base_url/base-url still only in Metadata (for example direct SDK registrations or Home refresh payloads, which bypass the file-store/synthesizer copy step), baseURL is still empty here and this line replaces it with cfg.ClaudeBaseURL. That breaks the documented per-auth override precedence for those supported metadata-backed auth paths; check cliproxyauth.BaseURLFromMetadata(a.Metadata) before falling back to the provider-wide value.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 2357dd5. @chatgpt-codex-connector please review again.
There was a problem hiding this comment.
Codex Review: Didn't find any major issues. 🎉
Reviewed commit: 2357dd51d2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Fixed in 2357dd5. @chatgpt-codex-connector please review again.
There was a problem hiding this comment.
Codex Review: Didn't find any major issues. More of your lovely PRs please.
Reviewed commit: 2357dd51d2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
ae57b1e to
2357dd5
Compare
|
Fixed the latest metadata base URL precedence feedback in 2357dd5. @chatgpt-codex-connector please review again. |
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Summary
Adds upstream base URL override support for OAuth/file-backed Claude and Codex credentials.
This addresses the same gap described in #4084: API-key credentials already support per-credential
base-url, but OAuth/file-backed credentials could not route requests through a local upstream gateway/compression/audit proxy without using the wrong layer (HTTP_PROXY/HTTPS_PROXY).Behavior
Resolution order for OAuth/file-backed credentials:
base_url/base-urlclaude-base-url/codex-base-urlExisting API-key credential
base-urlbehavior is unchanged and remains per-credential.Config examples
Provider-wide fallback:
Per OAuth auth file override:
{ "type": "codex", "email": "account@example.com", "base_url": "http://127.0.0.1:18101" }base-urlis also accepted as an alias.Validation
go test ./...go build -buildvcs=false -o test-output ./cmd/server